import State from '../common/state'
import basElem from '../common/baseElem'
import { Queue } from '../utils'

class NFAState extends State {}

class NFAGraph {

    public start: NFAState

    public end: NFAState

    constructor(start: NFAState, end: NFAState) {
        this.start = start
        this.end = end
    }

    public addParallelGraph(nfaGraph: NFAGraph) {
        let newStart = new NFAState()
        let newEnd = new NFAState()
        newStart.addNext(basElem.EPSILON, this.start)
        newStart.addNext(basElem.EPSILON, nfaGraph.start)
        this.end.addNext(basElem.EPSILON, newEnd)
        nfaGraph.end.addNext(basElem.EPSILON, newEnd)
        this.end = newEnd
        this.start = newStart
    }

    public addSeriesGraph(nfaGraph: NFAGraph) {
        this.end.addNext(basElem.EPSILON, nfaGraph.start)
        this.end = nfaGraph.end
    }

    public zeroMore() {
        this.oneMore()
        this.zeroOne()
    }

    public oneMore() {
        let newStart = new NFAState()
        let newEnd = new NFAState()
        newStart.addNext(basElem.EPSILON, this.start)
        this.end.addNext(basElem.EPSILON, newEnd)
        this.end.addNext(basElem.EPSILON, this.start)
        this.start = newStart
        this.end = newEnd
    }

    public zeroOne() {
        this.start.addNext(basElem.EPSILON, this.end)
    }

    public print() {
        console.log('>>>>>>>>>>>nfa<<<<<<<<<<')

        let que = new Queue<State>(),
            statePath: Set<number> = new Set()
            statePath.add(this.start.id)
            que.push(this.start)

        while(!que.empty) {
            let curState = que.poll()
            for(let entry of curState.next.entries()) {
                let key = entry[0],
                    nextStates = entry[1]
                for(let nextState of nextStates) {
                    console.log(`${curState.id} -> ${nextState.id}:  ${key}`)
                    if(!statePath.has(nextState.id)) {
                        que.push(nextState)
                        statePath.add(nextState.id)
                    }
                }
            }
        }

        console.log('>>>>>>>>>>>end<<<<<<<<<<')
    }

}

export default NFAGraph

export { NFAGraph, NFAState }